package com.Algorithm;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.Algorithm.Interface.DecisionMakingInterface;
import com.Entity.Employee;

public class AHP implements DecisionMakingInterface {

    private List<double[][]> criterionOfEmployees;
    private List<Employee> employeesIn;
    public double consistencyIndex;
    private double randomIndex = 1.25;
    private double[][] criterionMatrix
            = {
                {1.00, 0.11, 0.14, 0.20, 0.33, 0.11},
                {9.00, 1.00, 3.00, 9.00, 3.00, 7.00},
                {7.00, 0.33, 1.00, 0.33, 7.00, 5.00},
                {5.00, 0.11, 3.00, 1.00, 0.17, 9.00},
                {3.00, 0.33, 0.14, 6.00, 1.00, 0.14},
                {9.00, 0.14, 0.20, 0.11, 7.00, 1.00}
            };

    public AHP(double[][] preferenceMatrix) {
        criterionMatrix = preferenceMatrix;
    }

    public AHP() {
  
    }
    
    @Override
    public void buildModel(List<Employee> employees) {
        employeesIn = employees;
        PreferenceMatrix pm = new PreferenceMatrix(employeesIn);
        this.criterionOfEmployees = pm.allPreferenceMatrix;
    }

    @Override
    public List<Variant> determineRanking() {
               
        double[][] criterionNormalizedMatrix = normalizationMatrix(criterionMatrix);
        
        for (int i = 0; i < criterionOfEmployees.size(); i++) {
            criterionOfEmployees.set(i,
                    normalizationMatrix(criterionOfEmployees.get(i)));
        }

        List<List<Double>> vectors = new ArrayList<List<Double>>();
        vectors.add(avgValueNormalizedMatrix(criterionNormalizedMatrix));

        for (int i = 0; i < criterionOfEmployees.size(); i++) {
            vectors.add(avgValueNormalizedMatrix(criterionOfEmployees.get(i)));
        }

        List<Variant> variants = new ArrayList();
        List<Double> ranking = countRanking(vectors);

        for (int i = 0; i < ranking.size(); i++) {
            variants.add(new Variant(employeesIn.get(i), ranking.get(i)));
        }

        Collections.sort(variants);
        consistencyIndex = getConsistencyIndex(criterionMatrix, vectors.get(0));
        return variants;
    }

    public double[][] normalizationMatrix(double[][] matrix) {

        double[][] normalizationedMatrix = new double[matrix.length][matrix[0].length];
        double oldValue;
        double columnSum;
        double newValue;

        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                oldValue = matrix[i][j];
                columnSum = columnSum(matrix, j);
                newValue = oldValue / columnSum;
                normalizationedMatrix[i][j] = newValue;
            }
        }

        return normalizationedMatrix;
    }

    private double columnSum(double[][] pMatrix, int pColumn) {
        double columnSum = 0;

        for (int j = 0; j < pMatrix[pColumn].length; j++) {
            columnSum += pMatrix[j][pColumn];
        }

        return columnSum;
    }

    public List<Double> avgValueNormalizedMatrix(double[][] matrix) {
        List<Double> avgValue = new ArrayList<>();

        for (int i = 0; i < matrix.length; i++) {
            double rowSum = (rowSum(matrix, i));
            avgValue.add(new Double(rowSum / matrix.length));
        }

        return avgValue;
    }

    private double rowSum(double[][] pMatrix, int pRow) {
        double rowSum = 0;

        for (int j = 0; j < pMatrix[pRow].length; j++) {
            rowSum += pMatrix[pRow][j];
        }

        return rowSum;
    }

    public List<Double> countRanking(List<List<Double>> vectors) {
        List<Double> ranking = new ArrayList<>();
        List<Double> vectorZero = vectors.get(0);

        for (int i = 0; i < vectors.get(1).size(); i++) {
            double r = 0;
            for (int j = 0; j < vectorZero.size(); j++) {
               
                r += vectorZero.get(j) * vectors.get(j + 1).get(i);
            }
            ranking.add(new Double(r));
        }

        return ranking;
    }

    public double getConsistencyIndex(double[][] pMatrix, List<Double> vector) {
        
        double lambdaMax=0;
        double n = pMatrix.length;
        double consistency = 0;        
        for(int i=0; i<pMatrix.length; i++)
        {
            double columnSum = 0;
            for (int j = 0; j < pMatrix[i].length; j++) 
            {
                columnSum += pMatrix[j][i];
            }
            lambdaMax += columnSum * vector.get(i);
        }
        
        consistency = (lambdaMax - n)/(n - 1);
        
        return consistency/randomIndex;
    }
    
}
